package com.chilly.other.jdk8.stream;

import org.junit.Test;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Stream;

/**
 * 获取流的两种方式:将集合装换为Stream流,及将数组转换为Stream流
 * <p>
 * Created by Chilly Cui on 2021/1/7.
 */
public class GetStreamWay {

    //将List集合装换为Stream流
    public void testList() {
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();
    }

    //将Set集合转换为Stream流
    public void testSet() {
        Set<String> set = new HashSet<>();
        Stream<String> stream = set.stream();
    }

    //将Map集合转换为Stream流
    public void testMap() {
        Map<Integer, String> map = new HashMap<>();

        //分别获取并存储键与值
        Set<Integer> integers = map.keySet();
        Collection<String> values = map.values();
        //将存储键与值的集合转换为Stream流
        Stream<Integer> key = integers.stream();
        Stream<String> value = values.stream();

        //获取键值对(键与值映射关系),并将其转换为Stream流
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        Stream<Map.Entry<Integer, String>> entry = entries.stream();
    }

    //将数组转换为Stream流
    public void testArray() {
        String[] array = {"a", "ab", "bc", "abc", "bcd", "abcd"};
        Stream<String> stream = Stream.of(array);
    }

    @Test
    public void testForEach() {
        String[] array = {"a", "bc", "abc", "bcd", "abcd"};

        //第一种方式
        Stream<String> stream = Arrays.stream(array);
        stream.forEach(element -> System.out.println(element));

        //第二种方式
        Stream<String> stream2 = Stream.of(array);
        stream2.forEach(System.out::println);
    }


    @Test
    public void testFilter() {
        String[] array = {"a", "bc", "abc", "bcd", "abcd"};
        Stream.of(array)
                .filter(element -> element.startsWith("a"))
                .filter(element -> element.length() > 3)
                .forEach(System.out::println); //abcd
    }


    //将String类型的数组元素装换为Integer类型并输出

    //Lambda表达式写法
    @Test
    public void testMapWithLambda() {
        String[] array = {"1", "2", "3", "4", "5"};
        Stream<String> stream = Stream.of(array);
        Stream<Integer> stream2 = stream.map((String string) -> {
            return Integer.valueOf(string);
        });
        stream2.forEach(element -> System.out.println(element));
    }

    //Lambda表达式简写
    @Test
    public void testMapWithSimpleLambda() {
        String[] array = {"1", "2", "3", "4", "5"};
        Stream.of(array)
                .map(string -> Integer.valueOf(string))
                .forEach(element -> System.out.println(element));
    }

    //方法引用写法
    @Test
    public void testMapWithMethodRef() {
        String[] array = {"1", "2", "3", "4", "5"};
        Stream.of(array)
                .map(Integer::valueOf)
                .forEach(System.out::println);
    }

    @Test
    public void testCount() {
        String[] array = {"a", "bc", "abc", "bcd", "abcd"};
        long count = Stream.of(array).filter(element -> element.startsWith("a")).count();
        System.out.println(count);
    }

    @Test
    public void testLimit() {
        String[] array = {"a", "bc", "abc", "bcd", "abcd"};
        Stream.of(array).limit(3).forEach(System.out::println);
    }

    //使用skip方法跳过数组中的前三个元素并输出
    @Test
    public void testSkip() {
        String[] array = {"a", "bc", "abc", "bcd", "abcd"};
        Stream.of(array).skip(3).forEach(System.out::println);
    }

    //如果有两个流,希望合并称为一个流,那么可以使用Stream接口的静态方法concat

    //通过合并两个数组中的元素得到新的流,并输出合并后的数组元素
    //Lambda表达式写法
    @Test
    public void testConcat() {
        String[] array1 = {"a", "abc"};
        String[] array2 = {"abcd", "abcde"};
        Stream<String> stream1 = Stream.of(array1);
        Stream<String> stream2 = Stream.of(array2);
        Stream<Serializable> concatStream = Stream.concat(stream1, stream2);
        concatStream.forEach(System.out::println);
    }

    //简写
    @Test
    public void testSimpleConcat() {
        String[] array1 = {"a", "abc"};
        String[] array2 = {"abcd", "abcde"};
        Stream.concat(Stream.of(array1), Stream.of(array2)).forEach(System.out::println);
    }
}
